package com.ihg.hiex.admin.web.controller.session.during;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.ihg.hiex.admin.entity.security.Login;
import com.ihg.hiex.admin.service.account.DelegateService;
import com.ihg.hiex.admin.service.session.SessionDuringService;
import com.ihg.hiex.admin.service.session.SessionFinanceManagementService;
import com.ihg.hiex.admin.service.session.SessionMeetingService;
import com.ihg.hiex.admin.service.session.SessionParticipatorService;
import com.ihg.hiex.admin.service.session.SessionService;
import com.ihg.hiex.admin.service.session.SessionTaskService;
import com.ihg.hiex.admin.web.resolver.Secure;
import com.ihg.hiex.entity.session.Session;
import com.ihg.hiex.entity.session.during.SessionCalibration;
import com.ihg.hiex.entity.session.during.SessionFinanceManagement;
import com.ihg.hiex.entity.session.during.SessionInBasket;
import com.ihg.hiex.entity.session.during.SessionInBasketAnswer;
import com.ihg.hiex.entity.session.meeting.SessionMeeting;
import com.ihg.hiex.entity.session.participator.SessionParticipator;
import com.ihg.hiex.entity.session.participator.Type;
import com.ihg.hiex.entity.session.task.SessionTask;
import com.ihg.hiex.entity.session.task.Status;
import com.ihg.hiex.entity.user.Delegate;

/**
 * 
 * @author mohanlan
 *
 */
@Controller
@RequestMapping("/sessions/{sessionId}")
@MenuSetting("menu-sessions")
public class DuringTimeLineController {
    
    @Autowired
    private SessionService sessionService;
    
    @Autowired
    private SessionMeetingService sessionMeetingService;
    
    @Autowired
    private SessionParticipatorService sessionParticipatorService;
    
    @Autowired
    private SessionTaskService sessionTaskService;
    
    @Autowired
    private DelegateService delegateService;
    
    @Autowired
    private SessionDuringService sessionDuringService;
    
    @Autowired
    private SessionFinanceManagementService sessionFinanceManagementService;
    
    /**
     * day one summary
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @SuppressWarnings("unchecked")
    @MenuSetting(value = "submenu-session-during-day-one")
    @RequestMapping(value = "/day-one-summary", method = RequestMethod.GET)
    public ModelAndView dayOne(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/day-one/admin-day-one-time-line");
        
        // 1. load session
        Session session = sessionService.load(Session.class, sessionId);
        modelAndView.addObject("session", session);
        
        if(session.getSessionPhase().isBefore()) {
        	modelAndView.setViewName("session/during/day-one/admin-not-during-error");
        	return modelAndView;
        }
        
        // 2. list sessionParticipator
        List<SessionParticipator> participators = sessionParticipatorService.list(session);
        modelAndView.addObject("participators", participators);
        List<Long> delegateIds = CollectionUtils.extractPropertyList(participators, "delegateId");
        
        int lastGroup = participators.size() % 4;
        modelAndView.addObject("lastGroup", lastGroup);
        modelAndView.addObject("participatorAmount", participators.size());
        
        // get delegate meeting task map by delegateId and name
        String[] parents = new String[]{"Guest Meeting", "Colleague Meeting", "Owner Meeting", "OLT Meeting"};
        Map<String, Map<String, SessionTask>> meetingTasks = sessionTaskService.listByName(session, parents, Type.DELEGATE);
        modelAndView.addObject("meetingTasks", meetingTasks);
        
        // get meeting task 
        List<String> names = Arrays.asList("Assessor Day One Opening&notifications", "Delegate Opening&notifications", "Mid-day Calibration");
        Map<String, SessionTask> taskMap = sessionTaskService.construct(session, names);
        modelAndView.addObject("taskMap", taskMap);
        
        // 4. list assessor meeting task map by parent and assessorId and delegateId and name
        Map<String, Map<String, Map<String, SessionTask>>> assessorTasks = sessionTaskService.list(session, parents, Type.ASSESSOR);
        modelAndView.addObject("assessorTasks", assessorTasks);
        
        // 5. list delegate meeting task map by parent and delegateId and name
        Map<String, Map<String, Map<String, SessionTask>>> delegateTasks = sessionTaskService.list(session, parents, Type.DELEGATE);
        modelAndView.addObject("delegateTasks", delegateTasks);
        
        // 6. list delegate In-basket status map by delegateId
        List<SessionInBasket> sessionInBaskets = sessionDuringService.listSessionInbasket(session, "In-basket Score");
        Map<String, List<SessionInBasketAnswer>> answers = sessionDuringService.listSessionInBasketAnswer(sessionInBaskets);
        Map<Long, Status> answerStatus = sessionDuringService.generateAnswerStatus(delegateIds, answers);
        modelAndView.addObject("answerStatus", answerStatus);
        
        return modelAndView;
        
    }
    
    /**
     * day two meetings
     * 
     * @param id
     * @param sessionId
     * @return
     */
    @SuppressWarnings("unchecked")
    @MenuSetting(value = "submenu-session-during-day-two")
    @RequestMapping(value = "/day-two-summary", method = RequestMethod.GET)
    public ModelAndView dayTwo(@Secure(property = "id") Long id, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/day-two/admin-day-two-time-line");
        
        // 1. load session
        Session session = sessionService.load(Session.class, sessionId);
        modelAndView.addObject("session", session);
        
        // 2 list peerMeeting 
        SessionMeeting peerMeeting = sessionMeetingService.load(session, "Peer Calibration", id);
        modelAndView.addObject("peerMeeting", peerMeeting);
        
        // 3. construct taskMap
        List<String> names = Arrays.asList("Assessor Day Two Opening", "Peer Calibration", "Report Quality Check");
        Map<String, SessionTask> taskMap = sessionTaskService.construct(session, names);
        modelAndView.addObject("taskMap", taskMap);
        
        // get session's all participator
        List<SessionParticipator> sessionParticipators = sessionParticipatorService.list(session);
        Map<String, List<SessionParticipator>> participators = CollectionUtils.constructMapValues(sessionParticipators, "subgroup");
        modelAndView.addObject("participators", participators);
        
        // get assessor's Scoring&Comments Finalization task
        List<SessionTask> finalTasks = sessionTaskService.listByName(session, "Scoring&Comments Finalization");
        Map<String, SessionTask> finalTask = CollectionUtils.constructMapValue(finalTasks, "assessor.id");
        modelAndView.addObject("finalTasks", finalTask);
        
        // get peer calibration status
        List<Long> delegateIds = CollectionUtils.extractPropertyList(sessionParticipators, "delegateId");
        List<Delegate> delegates = delegateService.list(delegateIds);
        Map<Long, Status> calibrationStatus = sessionTaskService.listCalibrationReportStatus(delegates, session, Type.ASSESSOR, new String[]{"Peer Calibration Competency", "Peer Calibration Comments", "Peer Calibration Recommendation"}, "Peer Calibration");
        modelAndView.addObject("calibrationStatus", calibrationStatus);
        
        // get delegate's Peer Calibration Report task
        List<SessionTask> reportTasks = sessionTaskService.listByName(session, "Peer Calibration Report");
        Map<String, SessionTask> reportTask = CollectionUtils.constructMapValue(reportTasks, "delegate.id");
        modelAndView.addObject("reportTasks", reportTask);
        
        return modelAndView;
        
    }
    
    /**
     * day three meetings
     * 
     * @param sessionId
     * @return
     */
    @SuppressWarnings("unchecked")
    @MenuSetting(value = "submenu-session-during-day-three")
    @RequestMapping(value = "/day-three-summary", method = RequestMethod.GET)
    public ModelAndView dayThree(@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/day-three/admin-day-three-time-line");
        
        // 1. load session
        Session session = sessionService.load(Session.class, sessionId);
        modelAndView.addObject("session", session);
        
        // 2. construct taskMap
        List<String> names = Arrays.asList("Development Workshop", "Assessor Coaching Skills Recap", "Delegate closing session", "Assessor closing session");
        Map<String, SessionTask> taskMap = sessionTaskService.construct(session, names);
        modelAndView.addObject("taskMap", taskMap);
        
        // 3. get session's all participator
        List<SessionParticipator> sessionParticipators = sessionParticipatorService.list(session);
        Map<String, List<SessionParticipator>> participators = CollectionUtils.constructMapValues(sessionParticipators, "subgroup");
        modelAndView.addObject("participators", participators);
        
        // 4. get feedback task
        List<SessionTask> feedbackTasks = sessionTaskService.listByName(session, "Feedback&Coaching");
        Map<String, SessionTask> feedbackTaskMap = CollectionUtils.constructMapValue(feedbackTasks, "delegate.id");
        modelAndView.addObject("feedbackTaskMap", feedbackTaskMap);
        
        // 5. get delegate's Peer Calibration Report task
        List<SessionTask> reportTasks = sessionTaskService.listByName(session, "Peer Calibration Report");
        Map<String, SessionTask> reportTask = CollectionUtils.constructMapValue(reportTasks, "delegate.id");
        modelAndView.addObject("reportTasks", reportTask);
        
        // 6. list calibration
        List<Long> delegateIds = CollectionUtils.extractPropertyList(sessionParticipators, "delegateId");
        List<SessionCalibration> sessionCalibrations = sessionDuringService.listSessionCalibration(session, delegateIds);
        Map<String, SessionCalibration> sessionCalibrationMap = CollectionUtils.constructMapValue(sessionCalibrations, "delegate.id");
        modelAndView.addObject("sessionCalibrationMap", sessionCalibrationMap);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param id
     * @return
     */
    @MenuSetting(value = "submenu-session-during-day-one")
    @RequestMapping(value = "/day-one-summary/follow-up", method = RequestMethod.GET)
    public ModelAndView followUp(@Secure Login login, @PathVariable("id") Long id) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/day-one/admin-day-one-follow-up");
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param delegateId
     * @return
     */
    @RequestMapping(path = "/day-one-summary/finance-management-analysis", method = RequestMethod.GET)
    public ModelAndView financeAnalysis(@Secure Login login,
                             @PathVariable("sessionId") Long sessionId,
                             @RequestParam("delegate") Long delegateId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/day-one/financial-management-analysis");
        
        Session session = sessionService.load(sessionId);
        Delegate delegate = delegateService.load(Delegate.class, delegateId);
        
        // load fininanceManagement
        SessionFinanceManagement sessionFinanceManagement = sessionFinanceManagementService.load(session, delegate);
        modelAndView.addObject("sessionFinanceManagement", sessionFinanceManagement);
        
        modelAndView.addObject("session", session);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param delegateId
     * @return
     */
    @RequestMapping(value = "/day-one-summary/ib-assessment", method = RequestMethod.GET)
    public ModelAndView introduction(@PathVariable("sessionId") Long sessionId,
                                     @RequestParam("delegate") Long delegateId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/day-one/ib-assessment-answer");
        
        Delegate delegate = delegateService.load(Delegate.class, delegateId);
        modelAndView.addObject("delegate", delegate);
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        SessionInBasket sessionInBasket = sessionDuringService.loadSessionInbasket(session, delegate);
        modelAndView.addObject("sessionInBasket", sessionInBasket);
        
        Map<String, Map<String, List<SessionInBasketAnswer>>> answers = sessionDuringService.listSessionInBasketAnswer(sessionInBasket);
        modelAndView.addObject("answers", answers);
        
        return modelAndView;
    }
    
}
